import hashlib,json
import os
import time

import requests
from django.http import HttpRequest, JsonResponse, HttpResponse
from django.core.cache import cache
from rest_framework import viewsets
from rest_framework.response import Response
from rest_framework.decorators import api_view,action
from rest_framework import exceptions

from .models import Notify
from .serializers import *
from api.settings import BASE_DIR
from teamup.auth import TeamUpTokenAuth


# ViewSets define the view behavior.
class UserViewSet(viewsets.ModelViewSet):
    queryset = User.objects.all()
    serializer_class = UserSerializer
    authentication_classes = [TeamUpTokenAuth]


# ViewSets define the view behavior.
class SpaceViewSet(viewsets.ModelViewSet):
    queryset = Space.objects.all()
    serializer_class = SpaceSerializer
    authentication_classes = [TeamUpTokenAuth]

    def get_queryset(self):
        owner = self.request.query_params.get('owner', None)
        user_id = self.request.query_params.get('user_id', None)
        name = self.request.query_params.get('name', None)
        # 获取用户创建的空间
        if owner is not None:
            queryset = Space.objects.filter(owner=owner).order_by('id')
        # 获取用户有关的空间(加入和创建的)
        elif user_id is not None:
            queryset = Space.objects.filter(users=user_id).order_by('id')
        elif name is not None:
            queryset = Space.objects.filter(name=name).order_by('id')
        else:
            queryset = super().get_queryset()
        return queryset

    @action(detail=True, methods=['post'])
    def add_user_to_space(self, request, *args, **kwargs):
        data = request.data
        space = self.get_object()
        user = User.objects.filter(pk=data['user_id']).first()
        if user:
            space.users.add(user)
        return Response({'msg': 'ok'})

    @action(detail=True, methods=['post'])
    def delete_user_from_space(self, request, *args, **kwargs):
        data = request.data
        space = self.get_object()
        if space.owner.id == data['user_id']:
            return Response({'msg': 'cant not delete yourself'}, status=403)
        user = User.objects.filter(pk=data['user_id']).first()
        if user:
            space.users.remove(user)
        return Response({'msg': 'ok'})

    @action(detail=True, methods=['put'])
    def change_space_name(self, request, *args, **kwargs):
        data = request.data
        space = self.get_object()
        if data['name'] is None or len(data['name']) > 20:
            return Response({'msg': 'space name can not be blank or long than 20 chars'}, status=403)
        space.name = data['name']
        space.save()
        return Response({'msg': 'ok'})

# ViewSets define the view behavior.


class PostViewSet(viewsets.ModelViewSet):
    queryset = Post.objects.all()
    serializer_class = None
    authentication_classes = [TeamUpTokenAuth]

    def get_serializer_class(self): # 重写了基类里面的get_serializer_class方法,这是固定写法
        if self.request.method in ['PUT','POST','PATCH']:
            serializers_class = PostSerializerForPOST
        elif self.request.method == 'GET':
            serializers_class = PostSerializerForGET
        return serializers_class

    def get_queryset(self):
        owner = self.request.query_params.get('owner', None)
        space_id = self.request.query_params.get('space_id', None)
        user_id = self.request.query_params.get('user_id', None)
        # 获取用户创建的活动、帖子
        if owner is not None:
            queryset = Post.objects.filter(owner=owner).order_by('-create_time')
        # 获取用户有关的活动
        elif user_id is not None:
            queryset = Post.objects.filter(users=user_id).order_by('-create_time')
        # 获取某空间下的活动
        elif space_id is not None:
            queryset = Post.objects.filter(space=space_id).order_by('-create_time')
        else:
            queryset = super().get_queryset()
        return queryset

    def update(self, request, *args, **kwargs):
        return super().update(request, *args, **kwargs)
    
    def list(self, request, *args, **kwargs):
        return super().list(request, *args, **kwargs)
    
    @action(detail=True,methods=['post'])
    def add_user_to_post(self, request, pk=None):
        data = request.data
        post = self.get_object()
        if post.users.count() >= post.max_persons:
            return Response({'msg': 'person num is full'},status=403)
        user = User.objects.filter(pk=data['user_id']).first()
        if user:
            post.users.add(user)
        return Response({'msg': 'ok'})
    
    @action(detail=True,methods=['post'])
    def delete_user_from_post(self, request, pk=None):
        data = request.data
        post = self.get_object()
        if post.owner.id == data['user_id']:
            # 自己不能退出自己创建的帖子
            return Response({'msg': 'cant not delete yourself'}, status=403)

        user = User.objects.filter(pk=data['user_id']).first()
        if user:
            post.users.remove(user.id)

        return Response({'msg': 'ok'}, status=200)



@api_view(['GET','POST'])
def upload(r:HttpRequest):
    '''
    文件上传接口
    '''
    res = {'msg':'', 'code':-1}
    # print(list(r.POST.items()))
    user_id = r.POST.get('user_id')
    user = User.objects.filter(pk=user_id).first()
    subfix = str(int(time.time()))
    fname = BASE_DIR / f'../static/teamup/avatar/{user.open_id}-{subfix}.jpg'
    inf = r.FILES['file']
    with open(fname,'wb') as outf:
        for chunk in inf.chunks():  # 防止大文件爆内存
            outf.write(chunk)
    user.avatar = f'/avatar/{user.open_id}-{subfix}.jpg'
    user.save()
    res['code'] = 1
    res['avatar'] = user.avatar
    return JsonResponse(res)



@api_view(['GET'])
def notify_text(r:HttpRequest):
    res = {'msg':'', 'code':-1}
    text = Notify.objects.all()[0].text
    res['code']=1
    res['data']=text
    return JsonResponse(res)


@api_view(['GET','POST'])
def sec_msg_check(r:HttpRequest):
    content =r.data.get('content')
    openid = r.data.get('openid')
    ACCESS_TOKEN = get_access_token()
    url = f'https://api.weixin.qq.com/wxa/msg_sec_check?access_token={ACCESS_TOKEN}'
    data={
        'content': content,
        'version': 2,
        'scene': 4,
        'openid': openid
    }
    res = requests.post(url,json=data)
    return JsonResponse(res.json())


def check_signature(signature,timestamp,nonce):
    token = 'wechatpush'
    tmpArr = [token, timestamp, nonce]
    tmpArr.sort()
    tmpStr = "".join(tmpArr)
    tmpStr = hashlib.sha1(tmpStr.encode()).hexdigest()

    if tmpStr == signature:
        return True
    else:
        return False
    

# 微信消息推送
def push(r:HttpRequest):
    signature = r.GET.get('signature')
    timestamp = r.GET.get('timestamp')
    nonce = r.GET.get('nonce')  # 随机数
    echostr = r.GET.get('echostr')  # 随机字符串
    print(signature)
    print(timestamp)
    print(nonce)
    print(echostr)

    if check_signature(signature,timestamp,nonce):
        return HttpResponse(echostr)
    

def get_access_token():
    appid = 'wx580677cbb6245c9d'
    secret = os.getenv('APP_SECRET')
    url = f'https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={appid}&secret={secret}'
    r = requests.get(url)
    access_token = r.json()['access_token']
    # r.json()['expires_in'] # 7200
    # {"errcode":40013,"errmsg":"invalid appid"}
    return access_token


@api_view(['GET','POST'])
def login(r:HttpRequest):
    res = {'msg':'', 'code':-1}

    # 判断token是否有效， 不用一登陆就存一个token
    # t = r.GET.get('token')
    # openid = cache.get(t)
    # if openid:
    #     res['code'] = 2
    #     user = User.objects.get(open_id=openid)
    #     res['user'] = UserSerializer(user).data
    #     res['msg'] = 'token没过期'
    #     return JsonResponse(res)
    
    user_code = r.data.get('code')
    if not user_code:
        res['msg'] = '请求缺少code'
        return JsonResponse(res)

    # code 2 session
    App_id = 'wx580677cbb6245c9d'
    
    App_secret = os.environ.get('APP_SECRET')
    api_url = 'https://api.weixin.qq.com/sns/jscode2session?appid={0}&secret={1}&js_code={2}&grant_type=authorization_code'
    get_url = api_url.format(App_id,App_secret,user_code)
    rr = requests.get(get_url,timeout=5)
    json_data = rr.json()
    
    openid:str = json_data.get('openid','')
    session_key:str = json_data.get('session_key','')
    unionid:str = json_data.get('unionid','')
    errmsg:str = json_data.get('errmsg','')

    if 'errcode' in rr:
        errcode:int = json_data['errcode']
        if errcode == 40029:
            res['msg'] = 'js_code无效'
        elif errcode == 45011:
            res['msg'] = 'API 调用太频繁，请稍候再试'
        elif errcode == 40226:
            res['msg'] = '高风险等级用户，小程序登录拦截。'
        elif errcode == 40226:
            res['msg'] = '系统繁忙，此时请开发者稍候再试。'
        return JsonResponse(res)

    if not openid:
        # 调试强制指定用户

        openid = '999999'
        # raise exceptions.ValidationError('登录错误')

    # 校验用户, 不存在则创建
    # User.objects.get_or_create(open_id=openid)
    # try:
    #     user = User.objects.get(open_id=openid)
    # except:
    #     user = User.objects.create(
    #         name='微信用户',
    #         avatar='/avatar/def_avatar.png',
    #         open_id='999999',
    #     )

    user = User.objects.filter(open_id=openid).first()
    if not user:
        user = User.objects.create(
            name='微信用户',
            avatar='/avatar/def_avatar.png',
            open_id=openid,
        )

    user.session_key = 'session_key'
    user.save()
    user_str = json.dumps(UserSerializer(user).data)

    # 保存token
    sha = hashlib.sha1()
    sha.update(openid.encode())
    sha.update(session_key.encode())
    token = sha.hexdigest()
    cache.set(token, user.open_id, timeout=24*3600)  # 过期时间: 小时
    
    res['code'] = 1
    res['token'] = token
    res['user'] = json.loads(user_str)
    res['msg'] = '登录成功'
    return JsonResponse(res)


def get_spaces_of_user(r:HttpRequest):
    pass

